<html>
<head>
<title>Reinventing the Slice</title>
<script type="text/javascript">
function cl( e){
	console.log(e);
}
function clj( e){
	console.log(JSON.stringify(e));
}
function json( e){
	return JSON.stringify(e);
}


function sdkCell(){
	this.id = null;
	this.candids = null;
	this.houses = null;
	switch( arguments.length){
		case 1:
			if( typeof arguments[0] == "string" || arguments[0] instanceof String)
				this.id = arguments[0];
			else {
				this.id = arguments[0].id || null;
				this.candids = arguments[0].candids || null;
				this.houses = arguments[0].houses || null;
			}
			break;
		case 2:
			this.id = arguments[0];
			if( typeof arguments[1] == "array" || arguments[1] instanceof Array)
				this.candids = arguments[1];
			else
				this.candids = new Array( arguments[1]);
			break;
		case 3:
			this.id = arguments[0];
			if( typeof arguments[1] == "array" || arguments[1] instanceof Array)
				this.candids = arguments[1];
			else
				this.candids = new Array( arguments[1]);
			this.houses = arguments[2];
			break;
	}
	
	this.contains = function ( candid) {
		return !!~this.candids.indexOf(candid);
	};
	
	this.isSolved = function (){ 
		return this.candids.length == 1;
	};
	
	this.enable = function( candid){
		if( !this.contains( candid))
			this.candids.push( candid);
	};
	
	this.disable = function( candid){
		if( candid instanceof Array)
			candid.forEach(function(CandidId){
				this.disable(CandidId);
			},this);
		else
			this.candids = this.candids.filter(function(Candid){
				return Candid != candid;
			});
	};
	
	this.only = function( candid){
		this.candids = new Array(1);
		this.candids[0] = candid;
	};
	
	this.swap = function ( candid){
		if( this.contains( candid))
			this.enable( candid);
		else
			this.disable( candid);
	};
	
	this.isInHouse = function( houseId){
		return !!~this.houses.indexOf( houseId );
	};
	
	this.applyHouses = function( new_houses){
		this.houses = new Array();
		for( var i =0; i< new_houses.length; i++){
			if( new_houses[ i].indexOf( this.id) >= 0)
				this.houses.push(i);
		}
	};
}



function sdkSlice( data){
	sliceBase.call( data);
	return data;
}

function sliceBase(){
		
	this.isSlice = function(){
		// Usefull?
		return true;
	};
	
	this.calcHouses = function(){
		// Usefull?
		var h2 = new Array();
		this.forEach(function(cell){
			h2=h2.concat( cell.houses);
		},this);
		
		this.houses = sdkHelper.makeUnique( h2 ); 
	};
	
	this.houseIterator = function(){
		// Usefull?
		return sdkHelper.makeUnique( this.houses);
	};
	
	this.isSolved = function(){
		return this.every(function( cell){
			cell.isSolved();
		});
	};
	
	this.disable = function( candid){
		return this.forEach( function(cell){
			cell.disable(candid);
		});
	};
	
	// Filter 
	this.filterBy = function( callback, context){
		return sdkSlice( this.filter( callback, context));
	};
	
	this.secludeCell = function( arg){
		return this.filterBy(function(cell){
				return cell.id != arg;
			});
	};
	
	this.filterByHouse = function( arg){
		return this.filterBy(function (cell) {
				return cell.isInHouse( arg);
			});
	};
	
	this.filterByHouses = function( arg){
		var ret = new Array();		
		var i=0;
		arg.forEach(function( houseId){
			ret = ret.concat( this.filterByHouse( houseId));
		},this);
		ret = sdkHelper.makeUniqueCells( ret);
		sdkHelper.makeSlice( ret );
		return ret;
	};
	
	this.filterByLength = function( arg){
		return this.filterBy( function (cell) {
				return cell.candids.length == arg;
			});
	};
	
	this.filterByCandid = function( arg){
		if( arguments.length == 1)
			return this.filterBy( function (cell) {
					return cell.contains( arg);
				});
		var temp = arguments.pop();
	};
	
	this.filterByCandids = function( arg){
		var ret = this;
		//ret = ret.concat( this);

		arg.forEach(function(candidId){
			ret = ret.filterByCandid(candidId);
		},this);

		return ret;
	};
	
	// Negations
	this.filterNotHouse = function( arg){
		return this.filterBy(function (cell) {
				return !cell.isInHouse( arg);
			});
	};
	
	this.filterNotHouses = function( arg){
		var ret = copy(this);
		arg.forEach(function( houseId){
			ret.concat( ret.filterNotHouse( houseId));
		});
		return ret;
	};
	
	this.filterNotLength = function( arg){
		return this.filterBy( function (cell) {
				return cell.candids.length != arg;
			});
	};
	
	this.filterNotCandid = function( arg){
		return this.filterBy( function (cell) {
				return !cell.contains( arg);
			});
	};
	
	this.filterNotCandids = function( arg){
		var ret = this;
		arg.forEach(function(candidId){
			ret.concat( ret.filterNotCandid(candidId));
		});
		return ret;
	};
	
	this.calcHouses();
}

var sdkHelper = {
	makeSlice : function ( who) {
		sliceBase.call( who);
		return who;
	},
	
	makeUnique : function( arr){
		arr = arr.sort();
		var arr2 = new Array();
		for( i =0; i< arr.length; i++){
			arr2.push( arr[i]);
			i = arr.lastIndexOf(arr[i]);
		}
		return arr2;
	},
	
	makeUniqueCells : function( arr){
		arr = arr.sort();
		
		var arr2 = new Array();
		for( i =0; i< arr.length; i++){
		
			arr2.push( arr[i]);

			var j=0;
			for( j= i+1; j< arr.length ; j++){
				
				if( arr[ j].id != arr[ i].id){
					break;
				}
			}

			i=j-1;

			
		}
		sdkHelper.makeSlice( arr2)
		return arr2;
	},
	
	setUnion : function(a1,a2){
		return sdkHelper.makeUnique(Array.concat(a1,a2));
	},
	
	setIntersection : function( a1, a2){
		var ret = new Array();
		a1.forEach(function(ele){
			if( !!~a2.indexOf(ele))
				ret.push(ele);
		});
		return sdkHelper.makeUnique(ret);
	},
	
	setSymDiff : function( a1, a2){
		var ret = new Array();
		a1.forEach(function(ele){
			if( !~a2.indexOf(ele))
				ret.push(ele);
		});
		a2.forEach(function(ele){
			if( !~a1.indexOf(ele))
				ret.push(ele);
		});
		return sdkHelper.makeUnique(ret);
	},
	
	sharedHouses : function( c1, c2 ){
		var ret = new Array();
		ret = sdkHelper.setIntersection( c1.houses, c2.houses);
		return ret;
	},
	
	sharedCandids : function( c1, c2){
		var ret = new Array();
		for( candidId in c1.candids)
			if( c2.contains( c2))
				ret.push( candidId);
		return ret;
	},
};

var field = [];
field.push( new sdkCell({"id":"c00","candids":["6"],"houses":["hr0","hc0","hb0"]}));
field.push( new sdkCell({"id":"c01","candids":["1","2","4","5","7","9"],"houses":["hr0","hc1","hb0"]}));
field.push( new sdkCell({"id":"c16","candids":["2","4","6","5","7"],"houses":["hr1","hc7","hb2"]}));

field = sdkSlice( field);

clj(field);
clj(field.filterByLength(1));




</script>
</head>
<body>


</body>
</html>